package com.github.lzm320a99981e.autocoding.domain.mybatis;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Mybatis 批量操作（手动提交事务）
 */
@SuppressWarnings("rawtypes")
@Service
public class BatchService {

    private static final int DEFAULT_BATCH_SIZE = 500;

	public void batchOnceMultiple(List entities, SqlSessionTemplate sqlSessionTemplate, String statement) {
        batchOnceMultiple(entities, sqlSessionTemplate, statement, DEFAULT_BATCH_SIZE);
    }

    public void batchOnceMultiple(List entities, SqlSessionTemplate sqlSessionTemplate, String statement, int batchSize) {
        batch(entities, sqlSessionTemplate, statement, true, batchSize);
    }

    public void batchOnceSingle(List entities, SqlSessionTemplate sqlSessionTemplate, String statement) {
        batchOnceSingle(entities, sqlSessionTemplate, statement, DEFAULT_BATCH_SIZE);
    }

    public void batchOnceSingle(List entities, SqlSessionTemplate sqlSessionTemplate, String statement, int batchSize) {
        batch(entities, sqlSessionTemplate, statement, false, batchSize);
    }

    private void batch(List entities, SqlSessionTemplate sqlSessionTemplate, String statement, boolean onceMultiple, int batchSize) {
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
        try {
            int total = entities.size();
            if (onceMultiple) {
                int endPos = 0;
                while (endPos < total) {
                    sqlSession.update(statement, entities.subList(endPos, Math.min(endPos + batchSize, total)));
                    endPos += batchSize;
                    sqlSession.commit();
                    sqlSession.clearCache();
                }
            } else {
                int index = 0;
                for (Object entity : entities) {
                    sqlSession.update(statement, entity);
                    if ((++index) % batchSize == 0) {
                        sqlSession.commit();
                        sqlSession.clearCache();
                    }
                }
                sqlSession.commit();
            }
        } catch (Exception e) {
            sqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            sqlSession.close();
        }
    }

}
